home *** CD-ROM | disk | FTP | other *** search
- /* +-------------------------------------------------------------------+ */
- /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com) | */
- /* | | */
- /* | Permission to use, copy, modify, and to distribute this software | */
- /* | and its documentation for any purpose is hereby granted without | */
- /* | fee, provided that the above copyright notice appear in all | */
- /* | copies and that both that copyright notice and this permission | */
- /* | notice appear in supporting documentation. There is no | */
- /* | representations about the suitability of this software for | */
- /* | any purpose. this software is provided "as is" without express | */
- /* | or implied warranty. | */
- /* | | */
- /* +-------------------------------------------------------------------+ */
-
- #include <X11/Intrinsic.h>
- #include <X11/StringDefs.h>
- #include <X11/cursorfont.h>
- #include <X11/Xos.h>
- #include <sys/time.h>
- #include "xpaint.h"
- #include "Paint.h"
- #include <math.h>
- #include "misc.h"
-
- #ifndef NOSTDHDRS
- #include <stdlib.h>
- #include <unistd.h>
- #endif
-
- typedef struct {
- Widget w;
- int useGauss;
- int x, y;
- XtIntervalId id;
- Boolean gcFlag, isTiled, trackDrawn, drawing;
- int lastX, lastY;
- int zoom;
- /*
- ** Borrowed from the info
- */
- GC gc, gcx;
- Pixmap drawable;
- Boolean isFat;
- } LocalInfo;
-
- static int radius = 10, density = 10, radius2 = 10 * 10, rate = 100;
- static Boolean style = True;
-
- /*
- ** By default everything uses drand48(),
- ** I was making more exceptions than inclusinsion.
- */
- #define USE_DRAND
-
- #if defined(SVR4) || defined(__osf__)
- #define SHORT_RANGE
- #else
- #ifndef random
- long random(void);
- #endif
- #if !defined(sco)
- int srandom(unsigned int);
- #endif
- #endif
-
- #ifdef USE_DRAND
- # ifdef random
- # undef random
- # undef srandom
- # endif
- # define srandom srand48
- # define RANDOM(s, f) (drand48() * (f - s) + s)
- #else
- # ifdef SHORT_RANGE
- # define RANGE 0x00000fff
- # else
- # define RANGE 0x0fffffff
- # endif
- # define RANDOM(s, f) (((double)(random() % RANGE) / (double)RANGE) * (f - s) + s)
- #endif
-
- static void gauss(int range, int *x, int *y)
- {
- float fac, r, v1, v2;
-
- do {
- v1 = RANDOM(-1.0, 1.0);
- v2 = RANDOM(-1.0, 1.0);
- r = v1 * v1 + v2 * v2;
- } while (r >= 1.0);
-
- fac = -2.0 * log(r) / r;
- if (fac <= 0.0)
- fac = 0.0;
- else
- fac = sqrt(fac) / 2.0;
-
- *x = (v1 * fac) * range;
- *y = (v2 * fac) * range;
- }
-
- static void draw(LocalInfo *l)
- {
- int i;
- XRectangle rect;
- union {
- XSegment s[512];
- XPoint p[512];
- } p;
-
- UndoGrow(l->w, l->x - radius, l->y - radius);
- UndoGrow(l->w, l->x + radius, l->y + radius);
-
- for (i = 0; i < density; i++) {
- int rx, ry;
-
- do {
- if (l->useGauss) {
- gauss(radius, &rx, &ry);
- } else {
- rx = RANDOM(-radius, radius);
- ry = RANDOM(-radius, radius);
- }
- } while (rx * rx + ry * ry > radius2);
-
- if (l->isTiled) {
- p.s[i].x1 = l->x + rx;
- p.s[i].y1 = l->y + ry;
- p.s[i].x2 = l->x + rx;
- p.s[i].y2 = l->y + ry;
- } else {
- p.p[i].x = l->x + rx;
- p.p[i].y = l->y + ry;
- }
- }
-
- XYtoRECT(l->x - radius, l->y - radius,
- l->x + radius, l->y + radius, &rect);
-
- if (l->isTiled) {
- XDrawSegments(XtDisplay(l->w), l->drawable, l->gc, p.s, density);
- if (!l->isFat)
- XDrawSegments(XtDisplay(l->w), XtWindow(l->w), l->gc, p.s, density);
- } else {
- XDrawPoints(XtDisplay(l->w), l->drawable, l->gc, p.p, density, CoordModeOrigin);
- if (!l->isFat)
- XDrawPoints(XtDisplay(l->w), XtWindow(l->w), l->gc, p.p, density, CoordModeOrigin);
- }
-
- PwUpdate(l->w, &rect, False);
- }
-
- static void drawEvent(LocalInfo *l)
- {
- draw(l);
- l->id = XtAppAddTimeOut(XtWidgetToApplicationContext(l->w),
- rate, (XtTimerCallbackProc)drawEvent, (XtPointer)l);
- }
-
- static void drawOutline(Widget w, LocalInfo *l, int x, int y, Boolean flag)
- {
- Display *dpy = XtDisplay(w);
- Window window = XtWindow(w);
- XArc arc;
-
- arc.width = radius * l->zoom * 2;
- arc.height = radius * l->zoom * 2;
- arc.angle1 = 0;
- arc.angle2 = 360 * 64;
-
- if (l->trackDrawn) {
- arc.x = l->lastX - radius * l->zoom;
- arc.y = l->lastY - radius * l->zoom;
- XDrawArcs(dpy, window, l->gcx, &arc, 1);
- l->trackDrawn = False;
- }
-
- if (flag) {
- arc.x = x - radius * l->zoom;
- arc.y = y - radius * l->zoom;
- XDrawArcs(dpy, window, l->gcx, &arc, 1);
-
- l->lastX = x;
- l->lastY = y;
- l->trackDrawn = True;
- }
- }
-
-
- static void press(Widget w, LocalInfo *l, XButtonEvent *event, OpInfo *info)
- {
- GC sgc;
- int width, rule, rule2;
- /*
- ** Check to make sure all buttons are up, before doing this
- */
- if ((event->state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)) != 0)
- return;
-
- l->x = event->x;
- l->y = event->y;
-
- l->useGauss = style;
- l->drawing = True;
- drawOutline(w, l, 0, 0, False);
-
- UndoStartPoint(w, info, event->x, event->y);
-
- l->drawable = info->drawable;
- l->isFat = info->isFat;
-
- XtVaGetValues(w, XtNlineWidth, &width,
- XtNfillRule, &rule,
- XtNlineFillRule, &rule2,
- NULL);
- if (!l->gcFlag)
- l->gcFlag = (width != 0);
-
- if (event->button == Button2) {
- sgc = info->second_gc;
- l->isTiled = (rule2 != FillSolid);
- } else if (event->button == Button1) {
- sgc = info->first_gc;
- l->isTiled = (rule != FillSolid);
- } else
- return;
-
- if (l->gcFlag) {
- if (l->gc == None)
- l->gc = XCreateGC(XtDisplay(w), info->drawable, 0, NULL);
- XCopyGC(XtDisplay(w), sgc, ~GCLineWidth, l->gc);
- } else {
- l->gc = sgc;
- }
-
- if (l->id == (XtIntervalId)NULL)
- drawEvent(l);
- else
- draw(l);
- }
-
- static void motion(Widget w, LocalInfo *l, XMotionEvent *event, OpInfo *info)
- {
- if (l->drawing && info->surface == opPixmap) {
- l->x = event->x;
- l->y = event->y;
-
- draw(l);
- } else if (!l->drawing && info->surface == opWindow) {
- l->zoom = info->zoom;
- drawOutline(w, l, event->x, event->y, True);
- }
- }
-
- static void release(Widget w, LocalInfo *l, XButtonEvent *event, OpInfo *info)
- {
- int mask;
-
- /*
- ** Check to make sure all buttons are up, before doing this
- */
- mask = Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask;
- switch (event->button) {
- case Button1: mask ^= Button1Mask; break;
- case Button2: mask ^= Button2Mask; break;
- case Button3: mask ^= Button3Mask; break;
- case Button4: mask ^= Button4Mask; break;
- case Button5: mask ^= Button5Mask; break;
- }
- if ((event->state & mask) != 0)
- return;
-
- if (l->id != (XtIntervalId)NULL)
- XtRemoveTimeOut(l->id);
-
- l->id = (XtIntervalId)NULL;
- l->drawing = False;
- }
-
- static void leave(Widget w, LocalInfo *l, XEvent *event, OpInfo *info)
- {
- drawOutline(w, l, 0, 0, False);
- }
-
-
- /*
- ** Those public functions
- */
- void SpraySetParameters(int r, int d, int sp)
- {
- radius = r;
- radius2 = r * r;
- density = d;
- rate = sp * 10;
- }
- Boolean SprayGetStyle()
- {
- return style;
- }
- void SpraySetStyle(Boolean flag)
- {
- style = flag;
- }
-
- static void *commonSprayAdd(Widget w, Boolean flag)
- {
- LocalInfo *l = XtNew(LocalInfo);
- static int inited = False;
-
- if (!inited) {
- srandom((int)time(0));
- inited = True;
- }
-
- l->w = w;
- l->id = (XtIntervalId)NULL;
- l->gc = None;
- l->gcx = GetGCX(w);
- l->gcFlag = False;
- l->useGauss = flag;
- l->trackDrawn = False;
- l->drawing = False;
-
- XtVaSetValues(w, XtNcompress, False,
- XtVaTypedArg, XtNcursor, XtRString, "spraycan", sizeof(Cursor), NULL);
-
- OpAddEventHandler(w, opPixmap, ButtonPressMask, FALSE, (OpEventProc)press, l);
- OpAddEventHandler(w, opWindow|opPixmap, PointerMotionMask, FALSE, (OpEventProc)motion, l);
- OpAddEventHandler(w, opPixmap, ButtonReleaseMask, FALSE, (OpEventProc)release, l);
- OpAddEventHandler(w, opWindow, LeaveWindowMask, FALSE, (OpEventProc)leave, l);
-
- return l;
- }
- void *SprayAdd(Widget w)
- {
- return commonSprayAdd(w, style);
- }
- void SprayRemove(Widget w, LocalInfo *l)
- {
- OpRemoveEventHandler(w, opPixmap, ButtonPressMask, FALSE, (OpEventProc)press, l);
- OpRemoveEventHandler(w, opWindow|opPixmap, PointerMotionMask, FALSE, (OpEventProc)motion, l);
- OpRemoveEventHandler(w, opPixmap, ButtonReleaseMask, FALSE, (OpEventProc)release, l);
- OpRemoveEventHandler(w, opWindow, LeaveWindowMask, FALSE, (OpEventProc)leave, l);
-
- if (l->gcFlag)
- XFreeGC(XtDisplay(w), l->gc);
- if (l->id != (XtIntervalId)NULL)
- XtRemoveTimeOut(l->id);
-
- XtFree((XtPointer)l);
- }
-
- void *SmearAdd(Widget w)
- {
- return commonSprayAdd(w, False);
- }
- void SmearRemove(Widget w, LocalInfo *l)
- {
- SprayRemove(w, l);
- }
-